import requests
import json
import base64
from urllib.parse import urljoin

class K3CloudApiSdk:
    """扩展金蝶云API SDK，添加login和logout方法"""
    
    def __init__(self, server_url):
        self.server_url = server_url
        self.acct_id = ""
        self.username = ""
        self.password = ""
        self.app_id = ""
        self.app_sec = ""
        self.lcid = 2052
        self.session = requests.Session()
        self.token = None
    
    def InitConfig(self, acct_id, username, app_id, app_sec, server_url=None, lcid=2052):
        """初始化SDK配置"""
        self.acct_id = acct_id
        self.username = username
        self.app_id = app_id
        self.app_sec = app_sec
        if server_url:
            self.server_url = server_url
        self.lcid = lcid
        return True
    
    def Init(self, config_path=None, config_node=None):
        """从配置文件初始化SDK"""
        import configparser
        
        if not config_path:
            return False
            
        try:
            config = configparser.ConfigParser()
            config.read(config_path)
            
            node = config_node if config_node else "config"
            
            self.acct_id = config.get(node, "X-KDApi-AcctID", fallback="")
            self.username = config.get(node, "X-KDApi-UserName", fallback="")
            self.app_id = config.get(node, "X-KDApi-AppID", fallback="")
            self.app_sec = config.get(node, "X-KDApi-AppSec", fallback="")
            server_url = config.get(node, "X-KDApi-ServerUrl", fallback="")
            if server_url:
                self.server_url = server_url
            self.lcid = config.getint(node, "X-KDApi-LCID", fallback=2052)
            return True
        except Exception as e:
            print(f"初始化配置失败：{str(e)}")
            return False
    
    def Login(self, username=None, password=None):
        """
        扩展方法：登录金蝶云
        
        Args:
            username (str): 用户名，如不提供则使用初始化时设置的用户名
            password (str): 密码
            
        Returns:
            bool: 登录成功返回True，失败返回False
        """
        try:
            username = username if username else self.username
            if not username or not password:
                return False
                
            api_url = urljoin(self.server_url, "Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc")
            
            # 构造登录参数
            login_data = {
                "acctID": self.acct_id,
                "username": username,
                "password": password,
                "lcid": self.lcid
            }
            
            # 添加API调用所需的头信息
            headers = {
                "Content-Type": "application/json",
                "X-KDApi-AcctID": self.acct_id,
                "X-KDApi-UserName": self.username,
                "X-KDApi-AppID": self.app_id,
                "X-KDApi-AppSec": self.app_sec,
                "Accept": "application/json"
            }
            
            # 发送请求
            response = self.session.post(api_url, headers=headers, data=json.dumps(login_data))
            
            # 检查响应
            if response.status_code == 200:
                result = response.json()
                if isinstance(result, dict) and result.get("LoginResultType") == 1:
                    # 保存会话信息
                    self.token = result.get("KDSVCSessionId", "")
                    return True
            
            return False
            
        except Exception as e:
            print(f"登录失败：{str(e)}")
            return False
    
    def Logout(self):
        """
        扩展方法：登出金蝶云
        
        Returns:
            bool: 登出成功返回True，失败返回False
        """
        try:
            if not self.token:
                return True  # 如果没有登录会话，视为成功
                
            api_url = urljoin(self.server_url, "Kingdee.BOS.WebApi.ServicesStub.AuthService.Logout.common.kdsvc")
            
            # 添加API调用所需的头信息
            headers = {
                "Content-Type": "application/json",
                "X-KDApi-AcctID": self.acct_id,
                "X-KDApi-UserName": self.username,
                "X-KDApi-AppID": self.app_id,
                "X-KDApi-AppSec": self.app_sec,
                "Accept": "application/json",
                "KDSVCSessionId": self.token
            }
            
            # 发送请求
            response = self.session.post(api_url, headers=headers)
            
            # 重置会话信息
            self.token = None
            self.session = requests.Session()
            
            # 检查响应
            if response.status_code == 200:
                return True
            
            return False
            
        except Exception as e:
            print(f"登出失败：{str(e)}")
            return False
    
    # 以下是内部方法，用于发送API请求
    def _json_default(self, obj):
        """JSON序列化处理函数"""
        from datetime import datetime, date
        if isinstance(obj, (datetime, date)):
            return obj.strftime("%Y-%m-%d")
        raise TypeError(f"Object of type {type(obj)} is not JSON serializable")

    def _execute_api(self, api_name, data):
        """执行API调用"""
        api_url = urljoin(self.server_url, api_name)
        
        headers = {
            "Content-Type": "application/json",
            "X-KDApi-AcctID": self.acct_id,
            "X-KDApi-UserName": self.username,
            "X-KDApi-AppID": self.app_id,
            "X-KDApi-AppSec": self.app_sec,
            "Accept": "application/json"
        }
        
        if self.token:
            headers["KDSVCSessionId"] = self.token
        
        # 记录简化的请求信息，便于调试
        print(f"API请求URL: {api_url}")
        print(f"API请求类型: {api_name.split('.')[-2]}")
        
        # 简化的请求内容展示
        if api_name.startswith("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save"):
            print(f"保存单据: FormId={data.get('FormId')}")
        elif api_name.startswith("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery"):
            print(f"查询单据: FormId={data.get('FormId')}, Filter={data.get('FilterString', '')}")
        elif api_name.startswith("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.View"):
            print(f"查看单据: FormId={data.get('FormId')}, Number={data.get('Number', '')}")
            
        # 构造金蝶云API期望的请求格式
        if api_name.startswith("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save"):
            # 对于Save接口，需要将data包装在"data"字段中
            json_data = json.dumps(data, ensure_ascii=False, default=self._json_default)
            # 从data中获取FormId，如果没有则使用默认值
            form_id = data.get('FormId', 'UNW_BIORDERDETAIL')
            request_data = {
                "formid": form_id,
                "data": json_data
            }
            response = self.session.post(api_url, headers=headers, json=request_data)
        elif api_name.startswith("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery"):
            # ExecuteBillQuery 仅需要 data 参数
            json_data = json.dumps(data, ensure_ascii=False, default=self._json_default)
            request_data = {
                "data": json_data
            }
            response = self.session.post(api_url, headers=headers, json=request_data)
        elif any(api_name.startswith(prefix) for prefix in [
            "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Delete",
            "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Submit",
            "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Audit",
            "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.UnAudit",
            "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.UnSubmit",
        ]):
            # 其他需要 data 的接口统一包装
            json_data = json.dumps(data, ensure_ascii=False, default=self._json_default)
            form_id = data.get('FormId', 'UNW_BIORDERDETAIL')
            request_data = {
                "formid": form_id,
                "data": json_data
            }
            response = self.session.post(api_url, headers=headers, json=request_data)
        else:
            # 其他接口直接发送data
            response = self.session.post(api_url, headers=headers, data=json.dumps(data, ensure_ascii=False))
        
        # 记录简化的响应信息
        print(f"API响应状态码: {response.status_code}")
        
        # 根据响应长度决定显示方式
        if len(response.text) > 100:
            try:
                resp_json = json.loads(response.text)
                if isinstance(resp_json, dict) and "Result" in resp_json:
                    status = resp_json.get("Result", {}).get("ResponseStatus", {})
                    is_success = status.get("IsSuccess", False)
                    errors = status.get("Errors", [])
                    if is_success:
                        print("API响应: 成功")
                    else:
                        print(f"API响应: 失败, 错误={errors}")
                else:
                    print(f"API响应: 结果类型={type(resp_json).__name__}, 长度={len(response.text)}")
            except:
                print(f"API响应: 无法解析JSON, 长度={len(response.text)}")
        else:
            print(f"API响应: {response.text}")
            
        return response.text
    
    # 以下是原有SDK的方法实现，重定向到_execute_api
    def Save(self, form_id, data):
        """保存表单数据"""
        api_url = f"Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save.common.kdsvc?format=1"
        
        # 确保data包含必要的参数
        if not isinstance(data, dict):
            data = {}
            
        # 如果存在Model并且Model是列表，转换为字典
        if "Model" in data and isinstance(data["Model"], list):
            data["Model"] = {"FEntity": data["Model"]}
            
        # 如果没有Model字段但存在FEntity，构建正确的Model结构
        if "Model" not in data and "FEntity" in data:
            data = {
                "Model": data
            }
            
        # 如果Model内部没有FormId，则添加
        if "Model" in data and "FormId" not in data["Model"]:
            data["Model"]["FormId"] = form_id
            
        # 添加必要的参数
        if "IsAutoSubmitAndAudit" not in data:
            data["IsAutoSubmitAndAudit"] = False
            
        if "NeedUpDateFields" not in data:
            data["NeedUpDateFields"] = []
        
        if "NeedReturnFields" not in data:
            data["NeedReturnFields"] = ["FID"]
            
        data["FormId"] = form_id
        
        return self._execute_api(api_url, data)
        
    def Delete(self, form_id, data):
        """删除表单数据"""
        api_url = f"Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Delete.common.kdsvc?format=1"
        data["FormId"] = form_id
        return self._execute_api(api_url, data)
        
    def View(self, form_id, data):
        """查看表单数据"""
        api_url = f"Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.View.common.kdsvc?format=1"
        data["FormId"] = form_id
        return self._execute_api(api_url, data)
        
    def Submit(self, form_id, data):
        """提交表单数据"""
        api_url = f"Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Submit.common.kdsvc?format=1"
        data["FormId"] = form_id
        return self._execute_api(api_url, data)
        
    def Audit(self, form_id, data):
        """审核表单数据"""
        api_url = f"Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Audit.common.kdsvc?format=1"
        data["FormId"] = form_id
        return self._execute_api(api_url, data)
        
    def UnAudit(self, form_id, data):
        """反审核表单数据"""
        api_url = f"Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.UnAudit.common.kdsvc?format=1"
        data["FormId"] = form_id
        return self._execute_api(api_url, data)
        
    def UnSubmit(self, form_id, data):
        """反提交表单数据"""
        api_url = f"Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.UnSubmit.common.kdsvc?format=1"
        data["FormId"] = form_id
        return self._execute_api(api_url, data)
        
    def ExecuteBillQuery(self, data):
        """执行单据查询"""
        api_url = f"Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery.common.kdsvc"
        response_text = self._execute_api(api_url, data)
        try:
            # 尝试解析响应JSON
            result = json.loads(response_text)
            if isinstance(result, dict) and "Result" in result and "ResponseStatus" in result:
                # 新版本格式
                if result.get("Result", {}).get("ResponseStatus", {}).get("IsSuccess", False):
                    return json.dumps(result.get("Result", {}).get("ResponseStatus", {}).get("SuccessEntitys", []))
                else:
                    return "[]"
            else:
                # 旧版本格式直接返回
                return response_text
        except Exception as e:
            print(f"解析ExecuteBillQuery响应时出错: {str(e)}")
            return "[]"
        
    def Metadata(self, data):
        """获取元数据"""
        api_url = f"Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Metadata.common.kdsvc"
        return self._execute_api(api_url, data) 